using System;
using System.Collections.Generic;
using System.Reflection;

namespace RikMigrations
{
    public class MigrationSearch
    {
        public Dictionary<string, List<MigrationAttribute>> Search(Assembly assembly)
        {
            Dictionary<string, List<MigrationAttribute>> foundMigrations = new Dictionary<string, List<MigrationAttribute>>();

            addMigrationToList(foundMigrations, ReadAssemblyLevelMigrations(assembly), null);

            foreach (Type t in assembly.GetExportedTypes())
                addMigrationToList(foundMigrations, ReadClassLevelMigrations(t), t);

            return foundMigrations;
        }

        private static MigrationAttribute[] ReadClassLevelMigrations(Type t)
        {
            return (MigrationAttribute[]) t.GetCustomAttributes(typeof (MigrationAttribute), false);
        }

        private static MigrationAttribute[] ReadAssemblyLevelMigrations(Assembly assembly)
        {
            return (MigrationAttribute[])assembly.GetCustomAttributes(typeof(MigrationAttribute), false);
        }

        private static void addMigrationToList(Dictionary<string, List<MigrationAttribute>> foundMigrations, MigrationAttribute[] migrationsAttributes, Type t)
        {
            foreach (MigrationAttribute migration in migrationsAttributes)
            {
                migration.ModuleName = migration.ModuleName ?? MigrationManager.DefaultModuleName;

                if (t != null)
                    migration.Type = t;

                if (!foundMigrations.ContainsKey(migration.ModuleName))
                    foundMigrations.Add(migration.ModuleName, new List<MigrationAttribute>());

                foundMigrations[migration.ModuleName].Add(migration);
            }
        }
    }
}